<?php
/**
 * Copyright (c) [2019] [吴跃忠]
 * [selibra] is licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 * http://license.coscl.org.cn/MulanPSL
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v1 for more details.
 */

namespace Selibra\Model;


/**
 * Class SFEntity
 * @method mixed set*($value)
 * @package selibra\model
 */
class SFEntity implements \ArrayAccess
{

    /**
     * @var array
     */
    protected $autoFields = [];


    /**
     * SFEntity constructor.
     * @param array|null $params
     */
    public function __construct(array $params = null)
    {
        if (!empty($params)) {
            foreach ($params as $key => $param) {
                $this->$key = $param;
            }
        }
        $this->__init();
    }


    protected function __init()
    {

    }


    public function setProperty($name, $value)
    {
        $this->$name = $value;
    }

    /**
     * Whether a offset exists
     * @link https://php.net/manual/en/arrayaccess.offsetexists.php
     * @param mixed $offset <p>
     * An offset to check for.
     * </p>
     * @return boolean true on success or false on failure.
     * </p>
     * <p>
     * The return value will be casted to boolean if non-boolean was returned.
     * @since 5.0.0
     */
    public function offsetExists($offset)
    {
        if (!isset($this->$offset)) {
            return false;
        }
        return true;
    }


    /**
     * Offset to retrieve
     * @link https://php.net/manual/en/arrayaccess.offsetget.php
     * @param mixed $offset <p>
     * The offset to retrieve.
     * </p>
     * @return mixed Can return all value types.
     * @since 5.0.0
     */
    public function offsetGet($offset)
    {
        $method = 'get' . ucfirst($offset);
        if (method_exists($this, $method)) {
            return $this->$method();
        }
        return $this->$offset;
    }


    /**
     * Offset to set
     * @link https://php.net/manual/en/arrayaccess.offsetset.php
     * @param mixed $offset <p>
     * The offset to assign the value to.
     * </p>
     * @param mixed $value <p>
     * The value to set.
     * </p>
     * @return void
     * @since 5.0.0
     */
    public function offsetSet($offset, $value)
    {
        $method = 'set' . ucfirst($offset);
        if (method_exists($this, $method)) {
            return $this->$method($value);
        }
        $this->$offset = $value;
    }


    /**
     * Offset to unset
     * @link https://php.net/manual/en/arrayaccess.offsetunset.php
     * @param mixed $offset <p>
     * The offset to unset.
     * </p>
     * @return void
     * @since 5.0.0
     */
    public function offsetUnset($offset)
    {
        $this->$offset = null;
    }


    /**
     * @return array
     */
    public function selectProperty()
    {
        $vars = get_class_vars(get_class($this));
        unset($vars['autoFields']);
        return $vars;
    }


    /**
     * @return array
     */
    public function toArrayData()
    {
        $property = $this->selectProperty();
        $data = [];
        foreach ($property as $key => $var) {
            $method = 'get' . ucfirst($key);
            if (method_exists($this, $method)) {
                $data[$key] = $this->$method();
            } else {
                if (null !== $this->$key) {
                    $data[$key] = $this->$key;
                }
            }

        }
        return $data;
    }


    /**
     * @return array
     */
    public function toPropertyArrayData()
    {
        $property = $this->selectProperty();
        $data = [];
        foreach ($property as $key => $var) {
            if( !is_null($this->$key) ){
                $data[$key] = $this->$key;
            }
        }
        return $data;
    }


    /**
     * @return array
     */
    public function getAutoFields(): array
    {
        return $this->autoFields;
    }
}